package edu.ccut.saturn.web.filter;

import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import edu.ccut.saturn.component.ComponentFactory;
import edu.ccut.saturn.component.IAuthorityResourceInfo;
import edu.ccut.saturn.component.IParameterContext;
import edu.ccut.saturn.component.SaturnAuthorityManager;
import edu.ccut.saturn.component.SaturnComponentException;
import edu.ccut.saturn.component.SaturnData;

public class AuthorityFilter implements Filter {

	private static final String SATURN_AUTORITY_USER = "__SATURN_AUTORITY_USER__"; //$NON-NLS-1$

	private static final String ERROR_MESSAGE_KEY = "__ERROR_MESSAGE__"; //$NON-NLS-1$

	//private static final String VERITY_RESOURCE_LOGIC_FULL_KEY = "bank::/Module/logic/IsResourceAvailable.logic";

	private static final String ERROR_PAGE = "/error.jsp"; //$NON-NLS-1$

//	private static final String LOGIN_PAGE = "/login.jsp";

	private static final String LOGIN_ACTION = "/edu.ccut.saturn.authority.impl::/loginModule/action/Login.action"; //$NON-NLS-1$

	private FilterConfig filterConfig = null;

	public void destroy() {
		this.filterConfig = null;
	}

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {

		HttpServletRequest httpRequest = (HttpServletRequest) request;
		String contextPath = httpRequest.getContextPath().toString();
		String requestUrl = httpRequest.getRequestURL().toString();

		String requestResource = getRequestResource(requestUrl, contextPath);

		if (this.isNoneAuthorityResource(requestResource)) {
			chain.doFilter(httpRequest, response);

		} else if (requestResource != null
				&& !requestResource.equals(LOGIN_ACTION)) {

			SaturnData user = (SaturnData) httpRequest.getSession().getAttribute(
					SATURN_AUTORITY_USER);

			if (user == null) {
				RequestDispatcher dispatcher = this.filterConfig
						.getServletContext().getRequestDispatcher(ERROR_PAGE);

				request.setAttribute(ERROR_MESSAGE_KEY, Messages.getString("AuthorityFilter.0")); //$NON-NLS-1$
				dispatcher.forward(request, response);

			} else {

				if (this.isAccess(user.getString("id"), //$NON-NLS-1$
						requestResource)) {

					chain.doFilter(httpRequest, response);

				} else {
					RequestDispatcher dispatcher = this.filterConfig
							.getServletContext().getRequestDispatcher(
									ERROR_PAGE);
					request.setAttribute(ERROR_MESSAGE_KEY, Messages.getString("AuthorityFilter.1")); //$NON-NLS-1$
					dispatcher.forward(request, response);
				}
			}

		} else {
			chain.doFilter(httpRequest, response);
		}
	}

	/**
	 * 判断是否允许访问
	 * 
	 * @param user
	 * @param requestURL
	 * @return flag
	 * @throws Exception
	 */
	/*private boolean isAccess(String userSerialno, String requestURL) {
		IComponent logic = null;

		try {
			logic = ComponentManager.getInstance().getComponent(
					VERITY_RESOURCE_LOGIC_FULL_KEY);

		} catch (SaturnComponentException e) {
			e.printStackTrace();
		}

		if (logic == null) {
			// if logic really equals null,
			// the saturn platform didn't have any component for authority,
			// so return true to access any resource
			return true;
		}

		IParameterContext parameterContext = ComponentFactory
				.createParameterContext();
		
		parameterContext.addParameter(userSerialno, String.class);
		parameterContext.addParameter(requestURL, String.class);
		parameterContext.addParameter(null, Boolean.class);

		try {
			logic.execute(parameterContext);

		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}

		return (Boolean) parameterContext.getParameterValue(2);
	}*/

	private boolean isAccess(String userSerialno, String requestURL) {
		if(isAdmin(userSerialno)){
			return true;
		}
		return getResourceInfoList(requestURL, userSerialno);
	}
	
	private boolean isAdmin(String userSerialno){
		boolean isAdmin = false;
		IParameterContext parameterContext = ComponentFactory
		.createParameterContext();
		Connection con = parameterContext.getConnection();
		Statement stmt = null;
		ResultSet result = null;
		String queryUserType = "select * from saturn_authority_user where id='"+userSerialno+"'";
		try {
			stmt = con.createStatement();
			result = stmt.executeQuery(queryUserType);
			while(result.next()){
				String user_type = result.getString("usertype");
				if("00".equals(user_type)){
					isAdmin = true;
				}
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			try {
				if(result!=null){
					result.close();
				}
				if(stmt!=null){
					stmt.close();
				}
				if(con!=null){
					con.close();
				} 
			}catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		return isAdmin;
	}
	private boolean resourceMapping(ArrayList<IAuthorityResourceInfo> resourceInfos,String title, String tier) {
		for (IAuthorityResourceInfo resourceInfo : resourceInfos) {
			String resourceValue = resourceInfo.getValue();
			int index = resourceValue.indexOf("/", 1); //$NON-NLS-1$
			resourceValue = resourceValue.substring(index);

			if ("/*".equals(resourceValue)) { //$NON-NLS-1$
				return true;

			} else if (resourceValue != null) {

				if (resourceValue.contains("*")) { //$NON-NLS-1$
					int separator = resourceValue
							.lastIndexOf("/"); //$NON-NLS-1$

					String resourcePath = resourceValue.substring(
							0, separator + 1);

					String resourceName = resourceValue
							.substring(separator + 1);

					return doMapping(resourcePath, resourceName,
							tier);

				} else if (tier.equals(resourceValue)) {
					return true;
				}
			}
		}
	return false;
}

	private ArrayList<String> getRoleResourceList(String userSerialno){
		ArrayList<String> list = new ArrayList<String>();
		IParameterContext parameterContext = ComponentFactory
		.createParameterContext();
		Connection con = parameterContext.getConnection();
		Statement stmt = null;
		ResultSet result = null;		
		String sql = "select SATURN_AUTHORITY_ROLE_RES.* from SATURN_AUTHORITY_ROLE_RES," + //$NON-NLS-1$
				"saturn_authority_user_role "+ //$NON-NLS-1$
			    "where saturn_authority_user_role.role_id = saturn_authority_role_res.role_id "+ //$NON-NLS-1$
			    "and saturn_authority_user_role.user_id= '"+userSerialno+"'"; //$NON-NLS-1$ //$NON-NLS-2$

		if(con!=null){
			try {
				stmt = con.createStatement();
				result = stmt.executeQuery(sql);
				while(result.next()){
					String resource = result.getString("resource_id"); //$NON-NLS-1$
					list.add(resource);
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}finally{
				try {
					if(result!=null){
						result.close();
					}
					if(stmt!=null){
						stmt.close();
					}
					if(con!=null){
						con.close();
					} 
				}catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
		return list;
	}
	
	private boolean getResourceInfoList(String resources,String userSerialno){
		ArrayList<IAuthorityResourceInfo> authorityResourceInfoList = new ArrayList<IAuthorityResourceInfo>();
		ArrayList<String> roleResourceList = getRoleResourceList(userSerialno);
		if (resources != null && !"".equals(resources)) { //$NON-NLS-1$
			int index = resources.indexOf("/", 1); //$NON-NLS-1$

			if (index > 0) {
				String title = resources.substring(1, index);
				String tier = resources.substring(index);
				if (title.endsWith("::")) { //$NON-NLS-1$
					title = title.substring(0, title.length() - 2);
				}
				try{
					List<IAuthorityResourceInfo> resourceInfos = SaturnAuthorityManager.getInstance()
											.getSpecieledBundleResources(title);
					if(resourceInfos!=null){
						for(IAuthorityResourceInfo resourceInfo :resourceInfos){
							for(String resourceId : roleResourceList){
								if(resourceId.equals(resourceInfo.getResourceKey())){
									authorityResourceInfoList.add(resourceInfo);
								}
							}
						}
						return resourceMapping(authorityResourceInfoList,title, tier);
					}
				} catch (SaturnComponentException e) {
					e.printStackTrace();
				}
			}
		}
		return false;
	}
	
	
	private boolean doMapping(String resourcePath, String resourceName,
			String tier) {

		if (resourcePath.endsWith("/**/")) { //$NON-NLS-1$

			if (!tier.startsWith(resourcePath)) {

				String path = resourcePath.substring(0,
						resourcePath.length() - 3);

				if (tier.startsWith(path)) {
					return doResourceNameMapping(resourceName, tier);
				}
				return false;
			}

		} else if (tier.startsWith(resourcePath)) {
			return doResourceNameMapping(resourceName, tier);
		}
		return false;
	}

	/**
	 * 对资源名的匹配
	 * 
	 * @return
	 */
	private boolean doResourceNameMapping(String resourceName, String tier) {
		int index = tier.lastIndexOf("/"); //$NON-NLS-1$
		String name = tier.substring(index + 1);
		int pointIndex = name.indexOf("."); //$NON-NLS-1$

		if (pointIndex <= 0 || pointIndex >= (name.length() - 1)) {
			return false;
		}

		if (resourceName.contains("*")) { //$NON-NLS-1$
			int nameSeparator = resourceName.indexOf("."); //$NON-NLS-1$
			String prefix = resourceName.substring(0, nameSeparator);
			String suffix = resourceName.substring(nameSeparator + 1);

			if (prefix != null && suffix != null) {

				if (prefix.equals("*")) { //$NON-NLS-1$

					if (suffix.equals("*")) { //$NON-NLS-1$
						return true;

					} else if (name.substring(name.indexOf(".") + 1).equals( //$NON-NLS-1$
							suffix)) {

						return true;
					}

				} else if (suffix.equals("*")) { //$NON-NLS-1$

					if (name.substring(0, name.indexOf(".")).equals(prefix)) { //$NON-NLS-1$
						return true;
					}

				} else if (name.equals(resourceName)) {
					return true;
				}
			}

		} else if (resourceName.equals(name)) {
			return true;
		}
		return false;
	}
	
	private boolean isNoneAuthorityResource(String requestResource) {
		return !SaturnAuthorityManager.getInstance().isNeedAuthorityResource(
				requestResource);
	}

	private String getRequestResource(String requestUrl, String contextPath) {
		String requestAction = requestUrl.substring(requestUrl
				.indexOf(contextPath)
				+ contextPath.length());

		if (requestAction.indexOf('?') > -1) {
			return requestAction.substring(0, requestAction.indexOf('?'));
		}

		return requestAction;
	}

	public void init(FilterConfig filterConfig) throws ServletException {
		this.filterConfig = filterConfig;
	}
}
